package model

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"log"
	"os"
	"strings"
	"tapay-bot/global"
	"tapay-bot/pkg/setting"
	"tapay-bot/pkg/util"
	"time"
)

var (
	DeleteCacheKeyOpt = "delete_cache_key_opt"
)

type Model struct {
	ID         uint32 `gorm:"primary_key" json:"id"`
	CreatedOn  uint32 `json:"created_on"`
	ModifiedOn uint32 `json:"modified_on"`
	DeletedOn  uint32 `json:"deleted_on"`
	IsDel      uint8  `json:"is_del"`
}

type SmallModel struct {
	ID         uint32 `gorm:"primary_key" json:"id"`
	CreatedOn  uint32 `json:"created_on"`
	ModifiedOn uint32 `json:"modified_on"`
}

type BigIntModel struct {
	ID         uint64 `gorm:"primary_key" json:"id"`
	CreatedOn  uint32 `json:"created_on"`
	ModifiedOn uint32 `json:"modified_on"`
}

type BigModel struct {
	ID         uint32 `gorm:"primary_key" json:"id"`
	CreatedBy  string `json:"created_by"`
	ModifiedBy string `json:"modified_by"`
	CreatedOn  uint32 `json:"created_on"`
	ModifiedOn uint32 `json:"modified_on"`
	DeletedOn  uint32 `json:"deleted_on"`
	IsDel      uint8  `json:"is_del"`
}

func NewDBEngine(databaseSetting *setting.DatabaseSettingS) (*gorm.DB, error) {
	if len(databaseSetting.Password) >= 300 {
		password, err := util.DecryptPKCS1v15("/opt/cert/private_key.pem", strings.ReplaceAll(databaseSetting.Password, "\n", ""))
		if err != nil {
			return nil, err
		}
		databaseSetting.Password = password
	}
	dsn := "%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local"
	dsn = fmt.Sprintf(dsn, databaseSetting.UserName, databaseSetting.Password, databaseSetting.Host,
		databaseSetting.DBName)
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer（日志输出的目标，前缀和日志包含的内容——译者注）
		logger.Config{
			SlowThreshold:             time.Second, // 慢 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound（记录未找到）错误
			Colorful:                  true,        // 禁用彩色打印
		},
	)
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{SingularTable: true},
		Logger:         newLogger,
	})
	sqlDB, err := db.DB()
	// SetMaxIdleConns 设置空闲连接池中连接的最大数量
	sqlDB.SetMaxIdleConns(10)

	// SetMaxOpenConns 设置打开数据库连接的最大数量。
	sqlDB.SetMaxOpenConns(100)

	// SetConnMaxLifetime 设置了连接可复用的最大时间。
	sqlDB.SetConnMaxLifetime(time.Hour)
	return db, err
}

func CheckExistById(db *gorm.DB, value interface{}, id uint32) (bool, error) {
	if db == nil {
		db = global.DBEngine
	}
	var total int64
	err := db.Model(value).Where("id = ?", id).Count(&total).Error
	if err != nil {
		return false, err
	}
	if total == 0 {
		return false, gorm.ErrRecordNotFound
	}
	return true, nil
}

func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if page == 0 {
			page = 1
		}
		switch {
		case pageSize > 100:
			pageSize = 100
		case pageSize <= 0:
			pageSize = 10
		}

		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

func IsNewPattern(cacheMember string) bool {
	return strings.Contains(cacheMember, "-")
}

func GetIdsFromCacheMember(cacheMember string) []string {
	if strings.Contains(cacheMember, "-") {
		return strings.Split(cacheMember, "-")
	} else if strings.Contains(cacheMember, "_") {
		return strings.Split(cacheMember, "_")
	}
	return nil
}

func GetUidFromCacheMember(cacheMember string) string {
	var uid string
	if strings.Contains(cacheMember, "-") {
		uid = strings.Split(cacheMember, "-")[1]
	} else if strings.Contains(cacheMember, "_") {
		uid = strings.Split(cacheMember, "_")[1]
	}
	return uid
}

func GetIdFromCacheMember(cacheMember string) string {
	var id string
	if strings.Contains(cacheMember, "-") {
		id = strings.Split(cacheMember, "-")[0]
	} else if strings.Contains(cacheMember, "_") {
		id = strings.Split(cacheMember, "_")[0]
	}
	return id
}
